home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / glass / glass.lha / GLASS / widgets / Signal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-01  |  13.9 KB  |  482 lines

  1. #include <X11/IntrinsicP.h>
  2. #include <X11/StringDefs.h>
  3. #include <X11/Xatom.h>
  4. #include <X11/Xmu/Atoms.h>
  5. #include "SignalP.h"
  6.  
  7. static XtResource resources[] = {
  8. #define offset(field) XtOffset(SignalWidget, signal.field)
  9.     /* {name, class, type, size, offset, default_type, default_addr}, */
  10.     { XtNtimeScale, XtCTimeScale, XtRInt, sizeof(int), offset(time_scale), XtRImmediate, (XtPointer)3},
  11.     { XtNsampleLength, XtCSampleLength, XtRInt, sizeof(int), offset(sample_length), XtRImmediate, 0},
  12.     { XtNsample, XtCSample, XtRInt, sizeof(int *), offset(sample), XtRImmediate, NULL},
  13.     { XtNlevels, XtCLevels, XtRInt, sizeof(int *), offset(levels), XtRImmediate, 0},
  14.     { XtNorigin, XtCOrigin, XtRInt, sizeof(int *), offset(origin), XtRImmediate, 0},
  15.     { XtNinternalHeight, XtCInternalHeight, XtRInt, sizeof(int), offset(internal_height), XtRImmediate, (XtPointer)4},
  16.     { XtNmaxSampleLength, XtCSampleLength, XtRInt, sizeof(int), offset(max_sample_length), XtRImmediate, 0},
  17.     { XtNeditable, XtCEditable, XtRBoolean, sizeof(Boolean), offset(editable), XtRImmediate, (XtPointer)True },
  18.     { XtNeditCallback, XtCEditCallback, XtRCallback, sizeof(XtCallbackList), offset(edit_callback), XtRImmediate, NULL},
  19.     { XtNtimeDivision, XtCTimeDivision, XtRInt, sizeof(int), offset(time_division), XtRImmediate, 0},
  20.     { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  21.         offset(foreground), XtRString, "XtDefaultForeground"},
  22. #undef offset
  23. };
  24.  
  25. static char translations[] = "Shift<Btn1Down>: raise()\n\
  26.     Shift<Btn2Down>: extend()\n\
  27.     Shift<Btn3Down>: lower()\n\
  28.         <Key>Delete: delete-selection()\n\
  29.     !<Btn1Down>: select-start()\n\
  30.     !<Btn1Motion>: extend-adjust()\n\
  31.     !<Btn1Up>: extend-end()\n\
  32.         !<Btn2Down>: insert-selection()\n\
  33.     !<Btn3Down>: extend-start()\n\
  34.     !<Btn3Motion>: extend-adjust()\n\
  35.     !<Btn3Up>: extend-end()";
  36.  
  37. static void raise();
  38. static void lower();
  39. static void extend();
  40. static void select_start();
  41. static void extend_start();
  42. static void extend_end();
  43. static void extend_adjust();
  44. static void insert_selection();
  45. static void delete_selection();
  46.  
  47. static XtActionsRec actions[] = {
  48.   { "raise", raise },
  49.   { "lower", lower },
  50.   { "extend", extend },
  51.   { "select-start", select_start },
  52.   { "extend-start", extend_start },
  53.   { "extend-end", extend_end },
  54.   { "extend-adjust", extend_adjust },
  55.   { "insert-selection", insert_selection },
  56.   { "delete-selection", delete_selection },
  57. };
  58.  
  59. static void Initialize();
  60. static void Destroy();
  61. static Boolean SetValues();
  62. static void Redisplay();
  63. static void Resize();
  64.  
  65. SignalClassRec signalClassRec = {
  66.   { /* core fields */
  67.     /* superclass        */    (WidgetClass) &simpleClassRec,
  68.     /* class_name        */    "Signal",
  69.     /* widget_size        */    sizeof(SignalRec),
  70.     /* class_initialize        */    NULL,
  71.     /* class_part_initialize    */    NULL,
  72.     /* class_inited        */    FALSE,
  73.     /* initialize        */    Initialize,
  74.     /* initialize_hook        */    NULL,
  75.     /* realize            */    XtInheritRealize,
  76.     /* actions            */    actions,
  77.     /* num_actions        */    XtNumber(actions),
  78.     /* resources        */    resources,
  79.     /* num_resources        */    XtNumber(resources),
  80.     /* xrm_class        */    NULLQUARK,
  81.     /* compress_motion        */    TRUE,
  82.     /* compress_exposure    */    TRUE,
  83.     /* compress_enterleave    */    TRUE,
  84.     /* visible_interest        */    TRUE,
  85.     /* destroy            */    Destroy,
  86.     /* resize            */    Resize,
  87.     /* expose            */    Redisplay,
  88.     /* set_values        */    SetValues,
  89.     /* set_values_hook        */    NULL,
  90.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  91.     /* get_values_hook        */    NULL,
  92.     /* accept_focus        */    NULL,
  93.     /* version            */    XtVersion,
  94.     /* callback_private        */    NULL,
  95.     /* tm_table            */    translations,
  96.     /* query_geometry        */    XtInheritQueryGeometry,
  97.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  98.     /* extension        */    NULL
  99.   },
  100.   { /* Fields for simple */
  101.     /* change_sensitive         */      XtInheritChangeSensitive
  102.   },
  103.   { /* signal fields */
  104.     /* empty            */    0
  105.   }
  106. };
  107.  
  108. WidgetClass signalWidgetClass = (WidgetClass)&signalClassRec;
  109.  
  110. static XPoint point(w,x,y)
  111. SignalWidget w;
  112. short x;
  113. short y;
  114. {
  115.   XPoint pt;
  116.   pt.x = x;
  117.   pt.y = w->core.height - (w->signal.internal_height+y*w->signal.spacing);
  118.   return(pt);
  119. }
  120.  
  121. static void
  122. PrepareData(w, sample, nsample, points, npoints, scale)
  123. SignalWidget w;
  124. int sample[];
  125. int nsample;
  126. XPoint **points;
  127. int *npoints;
  128. int scale;
  129. {
  130.   int x = 0, j = 0, i;
  131.   int current;
  132.   XPoint *p ;
  133.  
  134. /* Free points and make npoint = 0 so this routine is correct even if no points are given */
  135.  
  136.   XtFree(*points);
  137.   *npoints = 0;
  138.   if(nsample==0)return;
  139.   p = (XPoint *)XtMalloc(2*nsample*sizeof(XPoint));
  140.   current = sample[0];
  141.   p[j++] = point(w, x, current);
  142.   for(i=1;i<nsample;i++){
  143.     x+=scale;
  144.     if(sample[i]!=current){
  145.       p[j++] = point(w,x,current);
  146.       p[j++] = point(w,x,current=sample[i]);
  147.     }
  148.   }
  149.   x+=scale;
  150.   p[j++] = point(w,x,current);
  151.   p = (XPoint *)XtRealloc(p,j*sizeof(XPoint));
  152.   for(i=j-1;i>0;i--){
  153.     p[i].x = p[i].x - p[i-1].x;
  154.     p[i].y = p[i].y - p[i-1].y;
  155.   }
  156.   *points = p;
  157.   *npoints = j;
  158. }
  159.  
  160. static void
  161. CheckLevels(sample, n, levels)
  162. int sample[];
  163. int n;
  164. int *levels;
  165. {
  166.   int i;
  167.   if(*levels!=0)return;
  168.   for(i=0;i<n;i++)if(sample[i]>*levels)*levels=sample[i];
  169.   (*levels)++;
  170. /* Check that level is never equal to 1 */
  171.   if(*levels<2)*levels=2;
  172. }
  173.  
  174. static void Recompute(w)
  175. SignalWidget w;
  176. {
  177.   CheckLevels(w->signal.sample, w->signal.sample_length, &(w->signal.levels));
  178.   w->signal.spacing = (w->core.height-2*w->signal.internal_height-1)/(w->signal.levels-1);
  179.   PrepareData(w, w->signal.sample, w->signal.sample_length,
  180.     &(w->signal.points), &(w->signal.npoints), w->signal.time_scale);
  181. }
  182.  
  183. static void Initialize(request, new)
  184. SignalWidget request, new;
  185. {
  186.   XGCValues values;
  187.   values.foreground = new->signal.foreground;
  188.   values.background = new->core.background_pixel;
  189.   new->signal.gc = XtGetGC(new, GCForeground | GCBackground, &values);
  190.   values.line_style = LineOnOffDash;
  191.   values.dashes = (char) 1;
  192.   new->signal.gc_div = XtGetGC(new, GCForeground | GCLineStyle | GCDashList , &values);
  193.   values.foreground = new->signal.foreground ^ new->core.background_pixel;
  194.   values.function = GXxor;
  195.   new->signal.xor_gc = XtGetGC(new, GCForeground | GCFunction, &values);
  196.   new->signal.points = NULL;
  197.   new->signal.npoints = 0;
  198.   if(new->core.height==0)new->core.height =30;
  199.   new->signal.sample = (int *)XtMalloc(new->signal.sample_length*sizeof(int));
  200.   bcopy(request->signal.sample, new->signal.sample, new->signal.sample_length*sizeof(int));
  201.   Recompute(new);
  202.   if(new->core.width==0){
  203.     if(new->signal.npoints > 0 && new->signal.points[new->signal.npoints-1].x > 0){
  204.       new->core.width = new->signal.points[new->signal.npoints-1].x+1;
  205.     } else {
  206.       new->core.width =10;
  207.     }
  208.   }
  209. }
  210.  
  211. static void Destroy(w)
  212. SignalWidget w;
  213. {
  214.   XtReleaseGC(w, w->signal.gc);
  215.   XtReleaseGC(w, w->signal.gc_div);
  216.   XtReleaseGC(w, w->signal.xor_gc);
  217. }
  218.  
  219. static Boolean SetValues(old, request, new)
  220. SignalWidget old, request, new;
  221. {
  222.   if(old->signal.sample != new->signal.sample){
  223.     int size = new->signal.sample_length*sizeof(int);
  224.     new->signal.sample = (int *)XtMalloc(size);
  225.     XtFree(old->signal.sample);
  226.     bcopy(request->signal.sample,new->signal.sample,size);
  227.   }
  228.   Recompute(new);
  229.   return(True);
  230. }
  231.  
  232. static void HighLight(w, from, to)
  233. SignalWidget w;
  234. int from, to;
  235. {
  236.   int From, To;
  237.   if(from==to)return;
  238.  
  239.   From = (from - w->signal.origin) * w->signal.time_scale;
  240.   To = (to - w->signal.origin) * w->signal.time_scale;
  241.   if(To > From){
  242.     XFillRectangle(XtDisplay(w), XtWindow(w), w->signal.xor_gc,
  243.         From, 0, To-From, w->core.height);
  244.   } else {
  245.     XFillRectangle(XtDisplay(w), XtWindow(w), w->signal.xor_gc,
  246.         To, 0, From-To, w->core.height);
  247.   }
  248. }
  249.  
  250. static void Redisplay(w)
  251. SignalWidget w;
  252. {
  253.   if(w->core.visible){
  254.     XClearWindow(XtDisplay(w), XtWindow(w));
  255.     if(w->signal.time_division>0){
  256.       int x = w->signal.origin % w->signal.time_division;
  257.       int first=(w->signal.time_division-x)*w->signal.time_scale;
  258.       for(;
  259.           first<w->core.width;
  260.           first += w->signal.time_division*w->signal.time_scale)
  261.         XDrawLine(XtDisplay(w),XtWindow(w),w->signal.gc_div,first,0,first,w->core.height);
  262.     }
  263.     w->signal.points[0].x = - w->signal.origin * w->signal.time_scale;
  264.     XDrawLines(XtDisplay(w),XtWindow(w),w->signal.gc,w->signal.points,w->signal.npoints, CoordModePrevious);
  265.     HighLight(w, w->signal.sel_start, w->signal.sel_end);
  266.   }
  267. }
  268.  
  269. static void Resize(w)
  270. SignalWidget w;
  271. {
  272.   Recompute(w);
  273. }
  274.  
  275. static int pick_unchecked(w, x)
  276. SignalWidget w;
  277. int x;
  278. {
  279.   return (x/w->signal.time_scale+w->signal.origin);
  280. }
  281.  
  282. static int pick(w, x)
  283. SignalWidget w;
  284. int x;
  285. {
  286.   int victim = pick_unchecked(w, x);
  287.   if(victim > w->signal.sample_length)victim=w->signal.sample_length;
  288.   return(victim);
  289. }
  290.  
  291. static void Edited(w)
  292. Widget w;
  293. {
  294.   Recompute(w);
  295.   XClearArea(XtDisplay(w), XtWindow(w),0,0,0,0,True);
  296.   XtCallCallbacks(w, XtNeditCallback, NULL);
  297. }
  298.  
  299. static void raise(w, event)
  300. SignalWidget w;
  301. XButtonPressedEvent *event;
  302. {
  303.   int victim = pick(w,event->x);
  304.   if(w->signal.editable && victim >= 0 && victim < w->signal.sample_length &&
  305.       w->signal.sample[victim]<(w->signal.levels-1)){
  306.     w->signal.sample[victim]++;
  307.     Edited(w);
  308.   }
  309. }
  310.  
  311. static void lower(w, event)
  312. SignalWidget w;
  313. XButtonPressedEvent *event;
  314. {
  315.   int victim = pick(w,event->x);
  316.   if(w->signal.editable && victim >= 0 && victim < w->signal.sample_length &&
  317.       w->signal.sample[victim]>0){
  318.     w->signal.sample[victim]--;
  319.     Edited(w);
  320.   }
  321. }
  322.  
  323. static void extend(w, event)
  324. SignalWidget w;
  325. XButtonPressedEvent *event;
  326. {
  327.   int victim = pick_unchecked(w,event->x);
  328.   int i;
  329.  
  330.   if(w->signal.editable && victim > w->signal.sample_length){
  331.     w->signal.sample = (int *)XtRealloc((char *)w->signal.sample, victim * sizeof(int));
  332.     for(i=w->signal.sample_length-1;i<victim;i++){
  333.       w->signal.sample[i] = w->signal.sample[w->signal.sample_length-1];
  334.     }
  335.     w->signal.sample_length = victim;
  336.     Edited(w);
  337.   }
  338. }
  339.  
  340. static void select_start(w, event)
  341. SignalWidget w;
  342. XButtonEvent *event;
  343. {
  344.   HighLight(w, w->signal.sel_start,w->signal.sel_end);
  345.   w->signal.sel_start = w->signal.sel_end = pick(w,event->x);
  346. }
  347. static void extend_start(w, event)
  348. SignalWidget w;
  349. XButtonEvent *event;
  350. {
  351.   int victim = pick(w,event->x);
  352.   if(abs(victim - w->signal.sel_end)>abs(victim - w->signal.sel_start)){
  353.     int t = w->signal.sel_end;
  354.     w->signal.sel_end = w->signal.sel_start;
  355.     w->signal.sel_start = t;
  356.   }
  357.   HighLight(w, victim, w->signal.sel_end);
  358.   w->signal.sel_end = victim;
  359. }
  360. static void canonize(from,to)
  361. int *from, *to;
  362. {
  363.     if(*from>*to){
  364.       int t = *to;
  365.       *to = *from;
  366.       *from =t;
  367.     }
  368. }
  369. #define XA_SAMPLING(d) XmuInternAtom(d,XmuMakeAtom("SAMPLING"))
  370. static Boolean
  371. convert_selection(w, selection, target, type_return, value_return,
  372.     length_return, format_return)
  373. SignalWidget w;
  374. Atom *selection;
  375. Atom *target;
  376. Atom *type_return;
  377. XtPointer *value_return;
  378. unsigned long *length_return;
  379. int *format_return;
  380. {
  381.   if(*selection != XA_PRIMARY){
  382.     XtWarning("Not selection owner!");
  383.     return(False);
  384.   }
  385.   if(*target == XA_TARGETS(XtDisplay(w))){
  386.     Atom *targets = (Atom *)XtMalloc(sizeof(Atom));
  387.     *targets = XA_SAMPLING(XtDisplay(w));
  388.     *value_return = (XtPointer) targets;
  389.     *length_return = 1;
  390.     return(True);
  391.   }
  392.   if(*target == XA_SAMPLING(XtDisplay(w))){
  393.     int size = abs(w->signal.sel_start-w->signal.sel_end);
  394.     char *new = (char *)XtMalloc(size*sizeof(int));
  395.     canonize(&(w->signal.sel_start),&(w->signal.sel_end));
  396.     bcopy(&(w->signal.sample[w->signal.sel_start]), new, size*sizeof(int));
  397.     *type_return = XA_SAMPLING(XtDisplay(w));
  398.     *value_return = new;
  399.     *length_return = size;
  400.     *format_return = 8*sizeof(int);
  401.     return(True);
  402.   }
  403.   return(False);
  404. }
  405. static void
  406. receive_selection(w, client_data, sel, type, value, length, format)
  407. SignalWidget w;
  408. XtPointer client_data;
  409. Atom *sel, *type;
  410. XtPointer value;
  411. unsigned long *length;
  412. int *format;
  413. {
  414.   if(*length>0){
  415.     int *newsample = (int *)XtMalloc((w->signal.sample_length+*length)*sizeof(int));
  416.     bcopy(w->signal.sample,newsample,(w->signal.sel_start)*sizeof(int));
  417.     bcopy(value,&(newsample[w->signal.sel_start]),(*length)*sizeof(int));
  418.     bcopy(&(w->signal.sample[w->signal.sel_start]),&(newsample[w->signal.sel_start+*length]),(w->signal.sample_length-w->signal.sel_start)*sizeof(int));
  419.     XtFree(w->signal.sample);
  420.     XtFree(value);
  421.     w->signal.sample = newsample;
  422.     w->signal.sample_length += *length;
  423.     Edited(w);
  424.   }
  425. }
  426.  
  427. static void delete_selection(w, event)
  428. SignalWidget w;
  429. XEvent *event;
  430. {
  431.   canonize(&(w->signal.sel_start),&(w->signal.sel_end));
  432.   if(w->signal.editable && w->signal.sel_start!=w->signal.sel_end){
  433.     int new_length = w->signal.sample_length-(w->signal.sel_end-w->signal.sel_start);
  434.     int *newsample = (int *)XtMalloc(new_length*sizeof(int));
  435.     bcopy(w->signal.sample,newsample,w->signal.sel_start*sizeof(int));
  436.     bcopy(&(w->signal.sample[w->signal.sel_end]),&(newsample[w->signal.sel_start]),(w->signal.sample_length-w->signal.sel_end)*sizeof(int));
  437.     XtFree(w->signal.sample);
  438.     w->signal.sample = newsample;
  439.     w->signal.sample_length = new_length;
  440.     XtDisownSelection(w, XA_PRIMARY, CurrentTime);
  441.     w->signal.sel_end = w->signal.sel_start;
  442.     Edited(w);
  443.   }
  444. }
  445.  
  446. static void insert_selection(w, event)
  447. SignalWidget w;
  448. XButtonEvent *event;
  449. {
  450.   if(w->signal.editable)
  451.     XtGetSelectionValue(w, XA_PRIMARY, XA_SAMPLING(XtDisplay(w)), 
  452.       receive_selection, NULL, event->time);
  453. }
  454.  
  455. static void
  456. lose_selection(w)
  457. SignalWidget w;
  458. {
  459.   HighLight(w, w->signal.sel_start,w->signal.sel_end);
  460.   w->signal.sel_end = w->signal.sel_start;
  461. }
  462. static void extend_end(w, event)
  463. SignalWidget w;
  464. XButtonEvent *event;
  465. {
  466.   int victim = pick(w,event->x);
  467.   HighLight(w, victim, w->signal.sel_end);
  468.   w->signal.sel_end = victim;
  469.   if(!XtOwnSelection(w, XA_PRIMARY, event->time, convert_selection, lose_selection, NULL)){
  470.     HighLight(w, w->signal.sel_start,w->signal.sel_end);
  471.     w->signal.sel_end = w->signal.sel_start;
  472.   }
  473. }
  474. static void extend_adjust(w, event)
  475. SignalWidget w;
  476. XButtonEvent *event;
  477. {
  478.   int victim = pick(w,event->x);
  479.   HighLight(w, victim, w->signal.sel_end);
  480.   w->signal.sel_end = victim;
  481. }
  482.